package ee.az.tetris.timer;

import java.util.HashSet;
import java.util.Set;

/**
 * @author Artur Zinatullin (artur.zinatullin@gmail.com) 2010
 */
public class Multitimer implements Runnable {

	private Set<TimerSlot> timers = new HashSet<TimerSlot>();

	public void run() {

		while (true) {
			for (TimerSlot slot : timers) { // run ticks
				if (slot.getNextTick() <= getCurrentTime()) {
					slot.setNextTick(slot.getNextTick() + slot.getTimer().getPeriod());
					slot.getTimer().tick();
				}
			}

			long timeout = Long.MAX_VALUE;
			for (TimerSlot slot : timers) { // select next timeout
				if (slot.getNextTick() - getCurrentTime() < timeout) {
					timeout = slot.getNextTick() - getCurrentTime();
				}
			}

			if (timeout > 0) {
				try {
					Thread.sleep(timeout); // Thread.sleep sleeps sometimes less (or more) than timeout or doesn't at all
				} catch (InterruptedException e) {
				}
			}
		}
	}

	public void addTimer(Timer timer) {
		TimerSlot slot = new TimerSlot(timer);
		slot.setNextTick(getCurrentTime() + timer.getPeriod());
		timers.add(slot);
	}

	private class TimerSlot {
		private Timer timer;
		private long nextTick;

		public TimerSlot(Timer timer) {
			this.timer = timer;
		}

		public long getNextTick() {
			return nextTick;
		}
		public void setNextTick(long nextTick) {
			this.nextTick = nextTick;
		}
		public Timer getTimer() {
			return timer;
		}
	}

	public static long getCurrentTime() {
		return System.currentTimeMillis();
	}
}

